/*************************************
 * Created by WebStorm
 * Author : 菲尔敦
 * QQ邮箱：2891044172@qq.com  手机号：15981761402
 * Created Time :2024/2/5 18:46
 Desc :
 **************************************/
import {AxiosTransform} from './AxiosTransform.ts'
import axios, {AxiosRequestConfig, AxiosResponse} from 'axios';
import {CreateAxiosOptions, RequestOptions, Result} from './type.ts';
import {deepMerge, setObjToUrlParams} from '@/util'
import {VAxios} from './VAxios.ts'
import {ContentTypeEnum, RequestEnum, ResultEnum} from './enums/httpEnum.ts';
import {isString, isUrl} from '@/util/is.ts';
import {formatRequestDate, joinTimestamp} from '@/util/http/helper.ts';
import {checkStatus} from './checkStatus.ts';
import {getToken, getTokenTime, setToken, setTokenTime} from "@/util/Auth.ts";
import {refreshToken} from '@/api/user.ts';

let isRefresh = false

const transformAxios: AxiosTransform = {
    // 请求之前处理config
    beforeRequestHook(config, options) {
        //获取系统当前时间
        const {joinPrefix, urlPrefix, joinParamsToUrl, formatDate, joinTime = true} = options;
        const isUrlStr = isUrl(config.url as string);
        if (!isUrlStr && joinPrefix) {
            config.url = `${urlPrefix}${config.url}`;
        }
        const params = config.params || {};
        const data = config.data || false;
        if (config.method?.toUpperCase() === RequestEnum.GET) {
            if (!isString(params)) {
                // 给 get 请求加上时间戳参数，避免从缓存中拿数据。
                config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
            } else {
                // 兼容restful风格
                config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
                config.params = undefined;
            }
        } else {
            if (!isString(params)) {
                formatDate && formatRequestDate(params);
                if (Reflect.has(config, 'data') && config.data && Object.keys(config.data).length > 0) {
                    config.data = data;
                    config.params = params;
                } else {
                    config.data = params;
                    config.params = undefined;
                }
                if (joinParamsToUrl) {
                    config.url = setObjToUrlParams(
                        config.url as string,
                        Object.assign({}, config.params, config.data)
                    );
                }
            } else {
                // 兼容restful风格
                config.url = config.url + params;
                config.params = undefined;
            }
        }
        return config;
    },
    //请求拦截器处理
    requestInterceptors(config: AxiosRequestConfig, options: CreateAxiosOptions) {
        // 请求之前处理config
        let token = getToken();
        //获取系统当前时间
        let currenTime:number = new Date().getTime();
        //获取token过期时间
        let expireTime:string|null=getTokenTime();

        //判断token是否过期
        if (expireTime!=null && parseInt(expireTime)>0){
            //没有过期、计算即将过期时间
            let min=(parseInt(expireTime)-currenTime)/1000/60;
            if (parseInt(String(min))<10 && parseInt(String(min))>0){
                //判断是否刷新token
                if (!isRefresh){
                    isRefresh=true;
                    refreshToken().then((res:any)=>{
                        setToken(res.data.token,res.data.expireTime);
                        setTokenTime(res.data.expireTime);
                        token=res.data.token;
                    }).catch(_error=>{}).finally(()=>{
                        isRefresh=false;
                    });
                }
            }
        }
        if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
            // jwt token
            (config as Recordable).headers.Authorization = options.authenticationScheme
                ? `${options.authenticationScheme} ${token}`
                :"Bearer "+token;
        }
        return config;
    },
    //响应拦截器
    transformResponseData(res: AxiosResponse<Result>, options: RequestOptions) {
        const {isTransformResponse} = options;
        // 不进行任何处理，直接返回
        // 用于页面代码可能需要直接获取code，data，message这些信息时开启
        if (!isTransformResponse) {
            return res.data;
        }
        // const $dialog = window['$dialog'];
        // const $message = window['$message'];
        const {data} = res;
        if (!data) {
            // return '[HTTP] Request has no return value';
            throw new Error('请求出错，请稍候重试');
        }
        //  这里 code，result，message为 后台统一的字段，需要修改为项目自己的接口返回格式
        const {code, message} = data;
        // 接口请求成功，直接返回结果
        if (code === ResultEnum.SUCCESS) {
            return data;
        }
        // 接口请求错误，统一提示错误信息 这里逻辑可以根据项目进行修改
        throw new Error(message);
    },
    /**
     * @description: 响应错误处理
     */
    responseInterceptorsCatch(error: any) {
        const $message = window['$message'];
        const $dialog = window['$dialog'];
        const {response, code, message} = error || {};
        const msg: string =
            response && response.data && response.data.message ? response.data.message : '';
        const err: string = error.toString();
        try {
            if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
                $message.error('接口请求超时，请刷新页面重试!');
                return;
            }
            if (err && err.includes('Network Error')) {
                $dialog.info({
                    title: '网络异常',
                    content: '请检查您的网络连接是否正常',
                    positiveText: '确定',
                    closable: false,
                    maskClosable: false,
                    onPositiveClick: () => {
                    },
                    onNegativeClick: () => {
                    },
                });
                return Promise.reject(error);
            }
        } catch (error) {
            throw new Error(error as any);
        }
        // 请求是否被取消
        const isCancel = axios.isCancel(error);
        if (!isCancel) {
            if (error.response.status === 500) {
                checkStatus(500)
            } else {
                checkStatus(code, msg)
            }
        } else {
            console.warn(error, '请求被取消！');
        }

        return Promise.reject(response?.data);
    }
}
function createAxios(opt?: Partial<CreateAxiosOptions>) {
    return new VAxios(deepMerge({
        timeout: 30 * 1000,//超时时间
        headers: {'Content-Type': ContentTypeEnum.FORM_DATA},//传输数据方式
        transformAxios,
        requestOptions: {
            // 默认将prefix 添加到url
            joinPrefix: true,
            // 接口拼接地址
            urlPrefix: "/api/admin/",
            //  是否加入时间戳
            joinTime: true,
            // 是否携带token
            withToken: true,
            // 忽略重复请求
            ignoreCancelToken: true,
            // 请求参数拼接到url
            joinParamsToUrl: false,
            // 格式化提交参数时间
            formatDate: true,
            // 不进行任何处理，直接返回
            isTransformResponse: false,
        }
    }, opt || {}))
}

export const http = createAxios();